﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;

namespace RSPJ.Windows
{
    public partial class Display : Form
    {
        int Lines, Samples;
        int[,,] dataArray;

        Point mouseDownPoint = new Point();
        bool isMove = false;
        int zoomStep = 100;
        Bitmap bmp;

        public Display(string title, int[,,] dataArray, int Lines,int Samples)
        {
            InitializeComponent();
            Text += "(" + title + ")";
            this.Lines = Lines;
            this.Samples = Samples;
            this.dataArray = dataArray;
        }

        // 实现图像的显示
        private void Display_Shown(object sender, EventArgs e)
        {
            Size = new Size(Lines + 200, Samples + 100);
            pbxDisplay.Size = new Size(Lines, Samples);

            bmp = new Bitmap(Samples, Lines);
            Graphics gp = Graphics.FromImage(bmp);
            gp.Clear(Color.White);
            for (int y = 0; y < Lines; y++)
            {
                for (int x = 0; x < Samples; x++)
                {
                    int r = dataArray[0, y, x];
                    int g = dataArray[1, y, x];
                    int b = dataArray[2, y, x];
                    Color color = Color.FromArgb(r, g, b);

                    gp.FillRectangle(new SolidBrush(color), x, y, 20, 20);
                }
            }
            gp.Save();

            pbxDisplay.Image = bmp;
            pbxDisplay.Left = (pnlDisplay.Width - pbxDisplay.Width) / 2;
            pbxDisplay.Top = (pnlDisplay.Height - pbxDisplay.Height) / 2;
        }

        // 实现图像的平移缩放
        private void Display_MouseDown(object sender, MouseEventArgs e)
        {
            pbxDisplay.Focus();
        }

        private void pnlDisplay_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Current = Cursors.Hand;
                mouseDownPoint.X = Cursor.Position.X;   //记录鼠标左键按下时位置
                mouseDownPoint.Y = Cursor.Position.Y;
                isMove = true;
            }
        }

        private void pnlDisplay_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Current = Cursors.Default;
                isMove = false;
            }
        }

        private void pnlDisplay_MouseMove(object sender, MouseEventArgs e)
        {
            pnlDisplay.Focus();  //鼠标不在picturebox上时焦点给别的控件，此时无法缩放            
            if (isMove)
            {
                int x, y;           //新的pbxDisplay.Location(x,y)
                int moveX, moveY;   //X方向，Y方向移动大小。
                moveX = Cursor.Position.X - mouseDownPoint.X;
                moveY = Cursor.Position.Y - mouseDownPoint.Y;
                x = pbxDisplay.Location.X + moveX;
                y = pbxDisplay.Location.Y + moveY;
                pbxDisplay.Location = new Point(x, y);
                mouseDownPoint.X = Cursor.Position.X;
                mouseDownPoint.Y = Cursor.Position.Y;
            }
        }

        private void pbxDisplay_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Current = Cursors.Hand;
                mouseDownPoint.X = Cursor.Position.X;   //记录鼠标左键按下时位置
                mouseDownPoint.Y = Cursor.Position.Y;
                isMove = true;
                pbxDisplay.Focus();    //鼠标滚轮事件(缩放时)需要picturebox有焦点
            }
        }

        private void pbxDisplay_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Cursor.Current = Cursors.Default;
                isMove = false;
            }
        }

        private void pbxDisplay_MouseMove(object sender, MouseEventArgs e)
        {
            pbxDisplay.Focus();    //鼠标在picturebox上时才有焦点，此时可以缩放
            if (isMove)
            {
                int x, y;           //新的pbxDisplay.Location(x,y)
                int moveX, moveY;   //X方向，Y方向移动大小。
                moveX = Cursor.Position.X - mouseDownPoint.X;
                moveY = Cursor.Position.Y - mouseDownPoint.Y;
                x = pbxDisplay.Location.X + moveX;
                y = pbxDisplay.Location.Y + moveY;
                pbxDisplay.Location = new Point(x, y);
                mouseDownPoint.X = Cursor.Position.X;
                mouseDownPoint.Y = Cursor.Position.Y;
            }

        }

        private void pbxDisplay_MouseWheel(object sender, MouseEventArgs e)
        {
            int x = e.Location.X;
            int y = e.Location.Y;
            int ow = pbxDisplay.Width;
            int oh = pbxDisplay.Height;
            int VX, VY;     //因缩放产生的位移矢量
            if (e.Delta > 0)    //放大
            {
                //第①步
                pbxDisplay.Width += zoomStep;
                pbxDisplay.Height += zoomStep;
                //第②步
                PropertyInfo pInfo = pbxDisplay.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                    BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbxDisplay, null);
                //第③步
                pbxDisplay.Width = rect.Width;
                pbxDisplay.Height = rect.Height;
            }
            if (e.Delta < 0)    //缩小
            {
                //防止一直缩成负值
                if (pbxDisplay.Width <= bmp.Width)
                    return;

                pbxDisplay.Width -= zoomStep;
                pbxDisplay.Height -= zoomStep;
                PropertyInfo pInfo = pbxDisplay.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                    BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(pbxDisplay, null);
                pbxDisplay.Width = rect.Width;
                pbxDisplay.Height = rect.Height;
            }
            //第④步，求因缩放产生的位移，进行补偿，实现锚点缩放的效果
            VX = (int)((double)x * (ow - pbxDisplay.Width) / ow);
            VY = (int)((double)y * (oh - pbxDisplay.Height) / oh);
            pbxDisplay.Location = new Point(pbxDisplay.Location.X + VX, pbxDisplay.Location.Y + VY);
        }

        private void Display_FormClosed(object sender, FormClosedEventArgs e)
        {
            Dispose();
        }
    }
}
